#ifndef JFUTUREINTERFACE_P_H
#define JFUTUREINTERFACE_P_H

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

#include <QtCore/qelapsedtimer.h>
#include <qcoreevent.h>
#include <QList>
#include <QWaitCondition>
#include "jrunnable.h"
#include "jconcurrentrunbase.h"

class JFutureCallOutEvent : public QEvent
{
public:
    enum CallOutType {
        Started,
        Finished,
        Canceled,
        Paused,
        Resumed,
        Progress,
        ProgressRange,
        ResultsReady
    };

    JFutureCallOutEvent()
        : QEvent(QEvent::FutureCallOut), callOutType(CallOutType(0)), index1(-1), index2(-1)
    { }
    JFutureCallOutEvent(CallOutType callOutType, int index1 = -1)
        : QEvent(QEvent::FutureCallOut), callOutType(callOutType), index1(index1), index2(-1)
    { }
    JFutureCallOutEvent(CallOutType callOutType, int index1, int index2)
        : QEvent(QEvent::FutureCallOut), callOutType(callOutType), index1(index1), index2(index2)
    { }

    JFutureCallOutEvent(CallOutType callOutType, int index1, const jstring &text)
        : QEvent(QEvent::FutureCallOut),
          callOutType(callOutType),
          index1(index1),
          index2(-1),
          text(text)
    { }

    CallOutType callOutType;
    int index1;
    int index2;
    jstring text;

    JFutureCallOutEvent *clone() const
    {
        return new JFutureCallOutEvent(callOutType, index1, index2, text);
    }

private:
    JFutureCallOutEvent(CallOutType callOutType,
                        int index1,
                        int index2,
                        const jstring &text)
        : QEvent(QEvent::FutureCallOut),
          callOutType(callOutType),
          index1(index1),
          index2(index2),
          text(text)
    { }
};

class JFutureCallOutInterface
{
public:
    virtual ~JFutureCallOutInterface() {}
    virtual void postCallOutEvent(const JFutureCallOutEvent &) = 0;
    virtual void callOutInterfaceDisconnected() = 0;
};

class JFutureInterfaceBasePrivate
{
public:
    JFutureInterfaceBasePrivate(JFutureInterfaceBase::State initialState);

    QAtomicInt refCount;
    mutable JMutex m_mutex;
    QWaitCondition waitCondition;
    QList<JFutureCallOutInterface *> outputConnections;
    int m_progressValue;
    int m_progressMinimum;
    int m_progressMaximum;
    JFutureInterfaceBase::State state;
    QElapsedTimer progressTime;
    QWaitCondition pausedWaitCondition;
    int pendingResults;
    JConcurrent::ResultStoreBase m_results;
    bool manualProgress;
    int m_expectedResultCount;
    JConcurrent::internal::ExceptionStore m_exceptionStore;
    jstring m_progressText;
    JRunnable *runnable;

    // Internal functions that does not change the mutex state.
    // The mutex must be locked when calling these.
    int internal_resultCount() const;
    bool internal_isResultReadyAt(int index) const;
    bool internal_waitForNextResult();
    bool internal_updateProgress(int progress, const jstring &progressText = jstring());
    void internal_setThrottled(bool enable);
    void sendCallOut(const JFutureCallOutEvent &callOut);
    void sendCallOuts(const JFutureCallOutEvent &callOut1, const JFutureCallOutEvent &callOut2);
    void connectOutputInterface(JFutureCallOutInterface *iface);
    void disconnectOutputInterface(JFutureCallOutInterface *iface);

    void setState(JFutureInterfaceBase::State state);
};

#endif  // JFUTUREINTERFACE_P_H
